W obecnej pracy domowej zastosujemy na naszym modelu metode Ceteris paribus skupiającą się na zmianach predykcji modelu wywoływanymi zmianami wartościi poszczególnych zmiennych. W poprzednich pracach zauważyliśmy, że wysoka zawartość alkoholu i siarczynów (sulphates) w większości przypadków wpływały na poprawę prognozowanej oceny. Wysoka całkowita zawartość dwutlenku siarki (total sulfur dioxide) za to zawszę tę ocenę obniżała. W analizie skupimy się na zweryfikowaniu tych wniosków.
import pandas as pd
import numpy as np
import dalex as dx
import pickle
np.random.seed = 46
df_wines = pd.read_csv('./src/winequality-red.csv')
df_wines["is_good"]=df_wines.apply(lambda row: 1 if row.quality > 5 else 0, axis = 1)
X = df_wines.drop(columns = ['quality','is_good'])
y = df_wines[['is_good']]
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state = 1613)
xgb_model = pickle.load(open('xgboost.sav', 'rb'))
explainer = dx.Explainer(xgb_model, X_train, y_train,label="XGBoost")
Preparation of a new explainer is initiated -> data : 1199 rows 11 cols -> target variable : Parameter 'y' was a pandas.DataFrame. Converted to a numpy.ndarray. -> target variable : 1199 values -> model_class : sklearn.model_selection._search.RandomizedSearchCV (default) -> label : XGBoost -> predict function : <function yhat_proba_default at 0x0000014EE9FA9C10> will be used (default) -> predict function : Accepts pandas.DataFrame and numpy.ndarray. -> predicted values : min = 0.0236, mean = 0.536, max = 0.99 -> model type : classification will be used (default) -> residual function : difference between y and yhat (default) -> residuals : min = -0.982, mean = -0.00296, max = 0.911 -> model_info : package sklearn A new explainer has been created!
X_train.iloc[314]
fixed acidity 7.0000 volatile acidity 0.6850 citric acid 0.0000 residual sugar 1.9000 chlorides 0.0670 free sulfur dioxide 40.0000 total sulfur dioxide 63.0000 density 0.9979 pH 3.6000 sulphates 0.8100 alcohol 9.9000 Name: 345, dtype: float64
xgb_model.predict(X_train.iloc[[314]])
array([0])
print("Predykcja modelu = " + str(xgb_model.predict(X_train.iloc[[314]])[0])+", prawdziwa wartość = " + str(y_train.iloc[[314]].iat[0,0]))
Predykcja modelu = 0, prawdziwa wartość = 0
explainer.predict_profile(X_train.iloc[314,:]).plot()
Calculating ceteris paribus: 100%|████████████| 11/11 [00:00<00:00, 305.69it/s]
Widzimy, że najważniejsza dla naszego modelu zmienna alkohol na badanej przez nas obserwacji do pewnego momentu zachowuje się w sposób jaki przewidzieliśmy. Ciekawy wydaje się być za to fakt, że od pewnej wartości prawdopodobieńswto predykcji wina jako dobrego spada i utrzymuje się na poziomie około 0.6. Jednak wyniki dla siarczynów i dwutlenku siarki dla tej obserwacji nie potwierdzają naszych przewidywań.
X_train.iloc[[10,222]]
| fixed acidity | volatile acidity | citric acid | residual sugar | chlorides | free sulfur dioxide | total sulfur dioxide | density | pH | sulphates | alcohol | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 332 | 8.0 | 0.58 | 0.28 | 3.2 | 0.066 | 21.0 | 114.0 | 0.9973 | 3.22 | 0.54 | 9.4 |
| 177 | 7.5 | 0.52 | 0.42 | 2.3 | 0.087 | 8.0 | 38.0 | 0.9972 | 3.58 | 0.61 | 10.5 |
explainer.predict_profile(X_train.iloc[[10,222],:]).plot()
Calculating ceteris paribus: 100%|████████████| 11/11 [00:00<00:00, 282.08it/s]
Dla dwóch powyższych obserwacji przy większości zmiennych wykresy wydają się iść równolegle. Jednak dla takich zmiennych jak pH, zawartość kwasu cytrynowego (citric acid) i kwasowość stała (fixed acidity) predykcje różnią się od siebie. Dla kwasowości stałej pierwsza obserwacja ma prawie stałą wartość predykcji 0.52. Druga obserwacja dla większości wartości ma mniejszą wartość predykcji po czym następuje skok, po którym utrzymuje prawdopodobieństwo na 0.6 . Także dla pH druga obserwacja zalicza skok w wartości 3.2 i rośnie w wartościach, w których pierwsza maleje. Dodatkowo przy niskiej zawartości kwasu cytrynowego wartość predykcji pierwszej obserwacji rośnie, a drugiej maleje. Ponadto widzimy, że wartości drugiej obserwacji są w większości przypadków bardziej zmienne, mają większe skoki i różnice w prawdoposobieństwach predykcji.
Badane przez nas obserwacje wykazały, że zależność między alkoholem, a oceną wina jest bardziej złożona niż myśleliśmy (wino słabe - złe, wino mocne - dobre). Nie zobaczyliśmy także nigdzie przewidywanych zależności między oceną, a zawartością siarczanów i tylko dla jednej obserwacji rosnąca zawartość dwutlenku siarki oznaczała spadek jakości wina. Obserwacje w większości miały podobne tendencje dla wybranych zmiennych jednak niektóre z nich miały większe skoki, spadki i różnice między wartościami.